home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / lpd / RCS / recvjob.c,v < prev    next >
Encoding:
Text File  |  1989-08-16  |  6.8 KB  |  352 lines

  1. head     1.1;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.1
  10. date     88.11.23.10.34.08;  author rab;  state Exp;
  11. branches ;
  12. next     ;
  13.  
  14.  
  15. desc
  16. @@
  17.  
  18.  
  19.  
  20. 1.1
  21. log
  22. @Initial revision
  23. @
  24. text
  25. @/*
  26.  * Copyright (c) 1983 Regents of the University of California.
  27.  * All rights reserved.
  28.  *
  29.  * Redistribution and use in source and binary forms are permitted
  30.  * provided that this notice is preserved and that due credit is given
  31.  * to the University of California at Berkeley. The name of the University
  32.  * may not be used to endorse or promote products derived from this
  33.  * software without specific prior written permission. This software
  34.  * is provided ``as is'' without express or implied warranty.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@@(#)recvjob.c    5.6 (Berkeley) 5/5/88";
  39. #endif /* not lint */
  40.  
  41. /*
  42.  * Receive printer jobs from the network, queue them and
  43.  * start the printer daemon.
  44.  */
  45.  
  46. #include "lp.h"
  47. #ifndef sprite
  48. #include <sys/fs.h>
  49. #endif
  50.  
  51. char    *sp = "";
  52. #define ack()    (void) write(1, sp, 1);
  53.  
  54. char    tfname[40];        /* tmp copy of cf before linking */
  55. char    dfname[40];        /* data files */
  56. int    minfree;        /* keep at least minfree blocks available */
  57. char    *ddev;            /* disk device (for checking free space) */
  58. int    dfd;            /* file system device descriptor */
  59.  
  60. char    *find_dev();
  61.  
  62. recvjob()
  63. {
  64.     struct stat stb;
  65.     char *bp = pbuf;
  66.     int status, rcleanup();
  67.  
  68.     /*
  69.      * Perform lookup for printer name or abbreviation
  70.      */
  71.     if ((status = pgetent(line, printer)) < 0)
  72.         frecverr("cannot open printer description file");
  73.     else if (status == 0)
  74.         frecverr("unknown printer %s", printer);
  75.     if ((LF = pgetstr("lf", &bp)) == NULL)
  76.         LF = DEFLOGF;
  77.     if ((SD = pgetstr("sd", &bp)) == NULL)
  78.         SD = DEFSPOOL;
  79.     if ((LO = pgetstr("lo", &bp)) == NULL)
  80.         LO = DEFLOCK;
  81.  
  82.     (void) close(2);            /* set up log file */
  83.     if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
  84.         syslog(LOG_ERR, "%s: %m", LF);
  85.         (void) open("/dev/null", O_WRONLY);
  86.     }
  87.  
  88.     if (chdir(SD) < 0)
  89.         frecverr("%s: %s: %m", printer, SD);
  90.     if (stat(LO, &stb) == 0) {
  91.         if (stb.st_mode & 010) {
  92.             /* queue is disabled */
  93.             putchar('\1');        /* return error code */
  94.             exit(1);
  95.         }
  96.     } else if (stat(SD, &stb) < 0)
  97.         frecverr("%s: %s: %m", printer, SD);
  98. #ifndef sprite
  99.     minfree = read_number("minfree");
  100.     ddev = find_dev(stb.st_dev, S_IFBLK);
  101.     if ((dfd = open(ddev, O_RDONLY)) < 0)
  102.         syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
  103. #else
  104.     /*
  105.      * Should have similar thing to check for free space...
  106.      */
  107. #endif
  108.     signal(SIGTERM, rcleanup);
  109.     signal(SIGPIPE, rcleanup);
  110.  
  111.     if (readjob())
  112.         printjob();
  113. }
  114.  
  115. #ifndef sprite
  116. char *
  117. find_dev(dev, type)
  118.     register dev_t dev;
  119.     register int type;
  120. {
  121.     register DIR *dfd = opendir("/dev");
  122.     struct direct *dir;
  123.     struct stat stb;
  124.     char devname[MAXNAMLEN+6];
  125.     char *dp;
  126.  
  127.     strcpy(devname, "/dev/");
  128.     while ((dir = readdir(dfd))) {
  129.         strcpy(devname + 5, dir->d_name);
  130.         if (stat(devname, &stb))
  131.             continue;
  132.         if ((stb.st_mode & S_IFMT) != type)
  133.             continue;
  134.         if (dev == stb.st_rdev) {
  135.             closedir(dfd);
  136.             dp = (char *)malloc(strlen(devname)+1);
  137.             strcpy(dp, devname);
  138.             return(dp);
  139.         }
  140.     }
  141.     closedir(dfd);
  142.     frecverr("cannot find device %d, %d", major(dev), minor(dev));
  143.     /*NOTREACHED*/
  144. }
  145. #endif /* sprite */
  146.  
  147. /*
  148.  * Read printer jobs sent by lpd and copy them to the spooling directory.
  149.  * Return the number of jobs successfully transfered.
  150.  */
  151. readjob()
  152. {
  153.     register int size, nfiles;
  154.     register char *cp;
  155.  
  156.     ack();
  157.     nfiles = 0;
  158.     for (;;) {
  159.         /*
  160.          * Read a command to tell us what to do
  161.          */
  162.         cp = line;
  163.         do {
  164.             if ((size = read(1, cp, 1)) != 1) {
  165.                 if (size < 0)
  166.                     frecverr("%s: Lost connection",printer);
  167.                 return(nfiles);
  168.             }
  169.         } while (*cp++ != '\n');
  170.         *--cp = '\0';
  171.         cp = line;
  172.         switch (*cp++) {
  173.         case '\1':    /* cleanup because data sent was bad */
  174.             rcleanup();
  175.             continue;
  176.  
  177.         case '\2':    /* read cf file */
  178.             size = 0;
  179.             while (*cp >= '0' && *cp <= '9')
  180.                 size = size * 10 + (*cp++ - '0');
  181.             if (*cp++ != ' ')
  182.                 break;
  183.             /*
  184.              * host name has been authenticated, we use our
  185.              * view of the host name since we may be passed
  186.              * something different than what gethostbyaddr()
  187.              * returns
  188.              */
  189.             strcpy(cp + 6, from);
  190.             strcpy(tfname, cp);
  191.             tfname[0] = 't';
  192.             if (!chksize(size)) {
  193.                 (void) write(1, "\2", 1);
  194.                 continue;
  195.             }
  196.             if (!readfile(tfname, size)) {
  197.                 rcleanup();
  198.                 continue;
  199.             }
  200.             if (link(tfname, cp) < 0)
  201.                 frecverr("%s: %m", tfname);
  202.             (void) unlink(tfname);
  203.             tfname[0] = '\0';
  204.             nfiles++;
  205.             continue;
  206.  
  207.         case '\3':    /* read df file */
  208.             size = 0;
  209.             while (*cp >= '0' && *cp <= '9')
  210.                 size = size * 10 + (*cp++ - '0');
  211.             if (*cp++ != ' ')
  212.                 break;
  213.             if (!chksize(size)) {
  214.                 (void) write(1, "\2", 1);
  215.                 continue;
  216.             }
  217.             strcpy(dfname, cp);
  218.             (void) readfile(dfname, size);
  219.             continue;
  220.         }
  221.         frecverr("protocol screwup");
  222.     }
  223. }
  224.  
  225. /*
  226.  * Read files send by lpd and copy them to the spooling directory.
  227.  */
  228. readfile(file, size)
  229.     char *file;
  230.     int size;
  231. {
  232.     register char *cp;
  233.     char buf[BUFSIZ];
  234.     register int i, j, amt;
  235.     int fd, err;
  236.  
  237.     fd = open(file, O_WRONLY|O_CREAT, FILMOD);
  238.     if (fd < 0)
  239.         frecverr("%s: %m", file);
  240.     ack();
  241.     err = 0;
  242.     for (i = 0; i < size; i += BUFSIZ) {
  243.         amt = BUFSIZ;
  244.         cp = buf;
  245.         if (i + amt > size)
  246.             amt = size - i;
  247.         do {
  248.             j = read(1, cp, amt);
  249.             if (j <= 0)
  250.                 frecverr("Lost connection");
  251.             amt -= j;
  252.             cp += j;
  253.         } while (amt > 0);
  254.         amt = BUFSIZ;
  255.         if (i + amt > size)
  256.             amt = size - i;
  257.         if (write(fd, buf, amt) != amt) {
  258.             err++;
  259.             break;
  260.         }
  261.     }
  262.     (void) close(fd);
  263.     if (err)
  264.         frecverr("%s: write error", file);
  265.     if (noresponse()) {        /* file sent had bad data in it */
  266.         (void) unlink(file);
  267.         return(0);
  268.     }
  269.     ack();
  270.     return(1);
  271. }
  272.  
  273. noresponse()
  274. {
  275.     char resp;
  276.  
  277.     if (read(1, &resp, 1) != 1)
  278.         frecverr("Lost connection");
  279.     if (resp == '\0')
  280.         return(0);
  281.     return(1);
  282. }
  283.  
  284. /*
  285.  * Check to see if there is enough space on the disk for size bytes.
  286.  * 1 == OK, 0 == Not OK.
  287.  */
  288. chksize(size)
  289.     int size;
  290. {
  291. #ifndef sprite
  292.     struct stat stb;
  293.     register char *ddev;
  294.     int spacefree;
  295.     struct fs fs;
  296.  
  297.     if (dfd < 0 || lseek(dfd, (long)(SBOFF), 0) < 0)
  298.         return(1);
  299.     if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
  300.         return(1);
  301.     spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024;
  302.     size = (size + 1023) / 1024;
  303.     if (minfree + size > spacefree)
  304.         return(0);
  305. #endif
  306.     return(1);
  307. }
  308.  
  309. read_number(fn)
  310.     char *fn;
  311. {
  312.     char lin[80];
  313.     register FILE *fp;
  314.  
  315.     if ((fp = fopen(fn, "r")) == NULL)
  316.         return (0);
  317.     if (fgets(lin, 80, fp) == NULL) {
  318.         fclose(fp);
  319.         return (0);
  320.     }
  321.     fclose(fp);
  322.     return (atoi(lin));
  323. }
  324.  
  325. /*
  326.  * Remove all the files associated with the current job being transfered.
  327.  */
  328. rcleanup()
  329. {
  330.  
  331.     if (tfname[0])
  332.         (void) unlink(tfname);
  333.     if (dfname[0])
  334.         do {
  335.             do
  336.                 (void) unlink(dfname);
  337.             while (dfname[2]-- != 'A');
  338.             dfname[2] = 'z';
  339.         } while (dfname[0]-- != 'd');
  340.     dfname[0] = '\0';
  341. }
  342.  
  343. frecverr(msg, a1, a2)
  344.     char *msg;
  345. {
  346.     rcleanup();
  347.     syslog(LOG_ERR, msg, a1, a2);
  348.     putchar('\1');        /* return error code */
  349.     exit(1);
  350. }
  351. @
  352.